#ifndef PROTOCOL_H
#define PROTOCOL_H

#include "errmsg.h" 

class Client;

//
// Rules for creating a protocol subclass:
//
//    Only ONE pending i/o operation is allowed per Client (file or net).
//       (violating this compromises the integrity of the Client
//		  and the whole server).
//	  I/O requests through Client::getNet() and Client::getFile() should be
//		 the last code in response to netIn/netOut, fileIn/fileEOF/FileErr.
//		 (violating this compromises the integrity of the Client
//		  and the whole server)
//	  The protocol drives all i/o for the Client while it's active.
//		 In particular, if the protocol needs more data it must request it
//		 (use Client::readNet()); otherwise, the Client will hang forever.
//	  Upon netIn(), the protocol must make calls to Client::eatIBuf() to
//		 flush the input buffer.
//	  Preceed all Client::getNet()->write() requests with a call to
//		 Client::setOUsed() with the amount to write (this will help detect
//		 short net write errors).
//****All calls to PatchServer::getPackageList() MUST be paired with a call to
//		 ..::releasePackageList() before requesting i/o.  Similarly
//		 with PatchServer::lockPackageList() and ..::unlockPackageList().  
//		 In other words, don't make a call to get(), req i/o, then release().
//		 FAILING TO OBSERVE THIS RULE *WILL RESULT IN SERVER DEADLOCK*!!
//		 The reason is only a small number of threads service all clients;
//		 blocking these threads stops all client i/o.
//		 (This rule applies to any object which requires synchronized access).
//	  After the protocol has finished, it must call Client::protocolDone()
//		 upon success or Client::errmsg() upon failure.
//	  Calling Client::close() deletes the client and the protocol itself;
//		 make sure the only code following this call is "return"
//
// These rules ensure that there aren't synchronization problems while accessing
// or modifying Client data.  Using these rules, while your protocol code is
// executing, no other thread can modify Client and mutual exclusion isn't
// necessary.  If the one pending i/o rule is too restrictive (e.g. need to post
// multiple file reads for higher performance), then the Client code (and
// all code that accesses/modifies it) must be augmented with mutual exclusion
// primitives (CriticalSections).  Error handling also would become more
// difficult.
//	  
// To activate the new protocol:
//	  Add a protocol identifier to Client::Protocols (before NumProtocols).
//	  Create the protocol in Client::Client().
//

class Protocol
{
	public:
		Protocol(Client* client);
		virtual ~Protocol();

		// decide whether protocol accepts request
		//
		virtual bool8 recognize(uint8* Msg, uint32 Len);

		// start the protocol with request:  errmsg.h result
		//
		virtual int32 start(uint8* Msg, uint32 Len);

		virtual void netIn(int32 Amt) = 0;
		virtual void netOut(int32 Amt) = 0;
		virtual void fileIn(int32 Amt);
		virtual void fileEOF();
		virtual void fileErr(uint32 Err);

	protected:
		Client* client;
};

inline
Protocol::Protocol(Client* client)
{
	this->client = client;
}

inline
Protocol::~Protocol()
{
}

inline bool8
Protocol::recognize(uint8* /*Msg*/, uint32 /*Len*/)
{
	return false;
}

inline int32
Protocol::start(uint8* /*Msg*/, uint32 /*Len*/)
{
	return EM_Success;
}

#endif
